#include <string>
#include <vector>
#include "opencl_runtime.h"
#include "CLKernel.h"

// TODO
// 普通卷积：
// 1. (Done) dataformat
// 2. (Done) 是否cedegen
// 3. (Done) 1个thread算多个
// winograd
// 1.在08模型上测试新shape
// 2.中间kernel的性能确认清楚，和超群的比
// 3.如果改变dataformat，性能ok？
// 4.local设置
// 其它
// 1.长宽不够用

int main(int argc, char const *argv[])
{
//    OpenCLRuntime::LogOpenCLInfo();
//    run_time->RunHello();

    auto storage_type = StorageType::TEXTURE_2D;
    auto layout = Layout::NC4HW4;
//    auto layout = Layout::NHWC4;

    auto data_type = DataType::FLOAT32;
//    auto data_type = DataType::FLOAT16;

    // Winograd目前仅支持NC4HW4/NC4HW4，要修改cl代码适配
    auto enable_winograd = true;
//    bool enable_winograd = false;

//    bool single_thread_2xFLT4 = true;
    bool single_thread_2xFLT4 = false;

    std::string attr_str, data_path;
    if (argc == 3)
    {
        data_path = std::string(argv[1]);
        attr_str = std::string(argv[2]);
    }
    else if (argc == 1)
    {
//        data_path = "testcases/mobilenetv2";
//        attr_str = "inputNHWC_1x224x224x3_outputNHWC_1x112x112x32_kernelHW_3x3_strideHW_2x2_padTopBottomLeftRight_0x1x0x1_dilationHW_1x1";
//        attr_str = "inputNHWC_1x7x7x320_outputNHWC_1x7x7x1280_kernelHW_1x1_strideHW_1x1_padTopBottomLeftRight_0x0x0x0_dilationHW_1x1";

//        data_path = "testcases/02";
//        attr_str = "inputNHWC_1x16x256x160_outputNHWC_1x16x256x100_kernelHW_1x1_strideHW_1x1_padTopBottomLeftRight_0x0x0x0_dilationHW_1x1";
//        attr_str = "inputNHWC_1x4x64x350_outputNHWC_1x4x64x150_kernelHW_1x1_strideHW_1x1_padTopBottomLeftRight_0x0x0x0_dilationHW_1x1";

//        data_path = "testcases/08";
//        attr_str = "inputNHWC_1x36x14400x128_outputNHWC_1x36x14400x128_kernelHW_1x1_strideHW_1x1_padTopBottomLeftRight_0x0x0x0_dilationHW_1x1";
//        attr_str = "inputNHWC_1x240x240x128_outputNHWC_1x240x240x128_kernelHW_1x1_strideHW_1x1_padTopBottomLeftRight_0x0x0x0_dilationHW_1x1";
//        attr_str = "inputNHWC_1x30x30x704_outputNHWC_1x30x30x512_kernelHW_1x1_strideHW_1x1_padTopBottomLeftRight_0x0x0x0_dilationHW_1x1";
//        attr_str = "inputNHWC_1x240x240x32_outputNHWC_1x240x240x16_kernelHW_1x1_strideHW_1x1_padTopBottomLeftRight_0x0x0x0_dilationHW_1x1";

//        data_path = "testcases/test";
//        attr_str = "inputNHWC_1x480x480x128_outputNHWC_1x480x480x128_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1";

        // 02 winograd tflite
        data_path = "testcases/test";
//        attr_str = "inputNHWC_1x16x256x96_outputNHWC_1x16x256x80_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1";
//        attr_str = "inputNHWC_1x16x256x100_outputNHWC_1x16x256x96_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1";
        attr_str = "inputNHWC_1x27x27x48_outputNHWC_1x27x27x192_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1";

        // 02 winograd others
//        data_path = "testcases/test";
//        attr_str = "inputNHWC_1x32x512x1_outputNHWC_1x32x512x50_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1"; // 1.02 vs 3.41=0.13 1.39 1.89
//        data_path = "testcases/test";
//        attr_str = "inputNHWC_1x32x512x50_outputNHWC_1x32x512x48_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1"; // 9.15 vs 5.63=1.5 3 1.13
//        attr_str = "inputNHWC_1x8x128x100_outputNHWC_1x8x128x250_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1"; // 6.11 vs 2.41=0.20 1.87 0.34
//        attr_str = "inputNHWC_1x8x128x100_outputNHWC_1x8x128x300_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1";// 7.11 vs 2.86=0.20 2.28 0.38
//        attr_str = "inputNHWC_1x4x64x150_outputNHWC_1x4x64x350_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1"; // 2.98 vs 1.51=0.12 1.21 0.18
//        attr_str = "inputNHWC_1x4x64x150_outputNHWC_1x4x64x400_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1"; // 3.32 vs 1.67=0.12 1.36 0.19

        // 08 winograd tflite
//        data_path = "testcases/test";
//        attr_str = "inputNHWC_1x480x480x128_outputNHWC_1x480x480x128_kernelHW_3x3_strideHW_1x1_padTopBottomLeftRight_1x1x1x1_dilationHW_1x1";
    }
    data_path += (data_type == DataType::FLOAT16) ? "_fp16" : "_fp32";

    auto kernel = ConvolutionKernel(storage_type, layout, data_type, attr_str, enable_winograd, single_thread_2xFLT4);
    kernel.Compile();
    kernel.InitMemory();
    kernel.SetInputData(data_path);
    kernel.BindArgs();
    kernel.Run(1);
    kernel.CompareOutput(data_path);
    return 0;
}